package graphics;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.BevelBorder;

import plots.Edge;
import plots.Plot;

import edu.uci.ics.jung.algorithms.layout.*;
import edu.uci.ics.jung.visualization.BasicVisualizationServer;

import agents.Agent;
import base.Environment;

public class EnvironmentView {	
	
	private final int HEIGHT = 800;
	private final int WIDTH = 1200;
	private final double TOP_HEIGHT_PERC = 0.25;
	private final double BOT_HEIGHT_PERC = 0.1;
	private final double[] TOP_PERC = {0.5, 0.2, 0.3};
	
	// Button scales
	private final int BUTTON_HEIGHT = 50;
	private final int BUTTON_WIDTH = 50;
	
	//	Animation speeds
	protected final int ANIMATION_TIMEOUT = 1000/30;
	protected final int HS_ANIMATION_TIMEOUT = 1000/70;	
	
	private int[] topWidths= new int[3];
	private Environment env;
	private JPanel panels[] = new JPanel[3];
	private BarGraph barGraph;
	private GraphView graphView;  
	
	
	
	private boolean simPlay;
	private boolean extendedSim;
	private boolean paralelSim;
	private int turnEndTimeout;
	private boolean paused = false;
			
	//	Sets the content of panels[0]
	private JPanel TopSectionC1(){
		JPanel result = barGraph.createInitialChartPanel();
		result.setPreferredSize(new Dimension(topWidths[0], 
				(int)(TOP_HEIGHT_PERC*HEIGHT)));
		result.setBorder(new BevelBorder(BevelBorder.LOWERED));
		return result;
	}
	
	private JPanel TopSectionC2(){
		JPanel result = new JPanel();
		result.setBorder(new BevelBorder(BevelBorder.LOWERED));
		result.setPreferredSize(new Dimension(topWidths[1], 
				(int)(TOP_HEIGHT_PERC*HEIGHT)));
		return result;
	}

	private JPanel TopSectionC3(){
		JPanel result = new JPanel();
		result.setBorder(new BevelBorder(BevelBorder.LOWERED));
		result.setPreferredSize(new Dimension(topWidths[2], 
				(int)(TOP_HEIGHT_PERC*HEIGHT)));

		return result;
	}

	private JPanel BottomSection(){
		JPanel result = new JPanel();
		result.setBorder(new BevelBorder(BevelBorder.LOWERED));
		result.setPreferredSize(new Dimension(WIDTH, (int)(BOT_HEIGHT_PERC*HEIGHT)));
		
		JButton play, playFF, stop, pause;		
		ImageIcon icon;
		
		//	Place simple buttons
		icon = new ImageIcon("ui\\play.png");
		icon = new ImageIcon(icon.getImage().getScaledInstance(BUTTON_WIDTH, BUTTON_HEIGHT, java.awt.Image.SCALE_SMOOTH));
		play = new JButton(icon);
		play.addActionListener(new PlayAction(this));
		
		icon = new ImageIcon("ui\\ffwd.png");
		icon = new ImageIcon(icon.getImage().getScaledInstance(BUTTON_WIDTH, BUTTON_HEIGHT, java.awt.Image.SCALE_SMOOTH));
		playFF = new JButton(icon);
		playFF.addActionListener(new PlayFFAction(this));

		icon = new ImageIcon("ui\\stop.png");
		icon = new ImageIcon(icon.getImage().getScaledInstance(BUTTON_WIDTH, BUTTON_HEIGHT, java.awt.Image.SCALE_SMOOTH));
		stop = new JButton(icon);
		stop.addActionListener(new StopAction(this));
		
		icon = new ImageIcon("ui\\bigstop.png");
		icon = new ImageIcon(icon.getImage().getScaledInstance(BUTTON_WIDTH, BUTTON_HEIGHT, java.awt.Image.SCALE_SMOOTH));
		pause = new JButton(icon);
		pause.addActionListener(new PauseAction(this));

		
		result.add(pause);
		result.add(play);
		result.add(playFF);
		result.add(stop);
		
		//	Place radio buttons
		JRadioButton chartOnly = new JRadioButton("Charts Only");
		JRadioButton extended = new JRadioButton("Extended View");
		JRadioButton paralel = new JRadioButton("Simultaneous View");
		ButtonGroup group = new ButtonGroup();
		
		RadioAction rad = new RadioAction(this);
		chartOnly.addActionListener(rad);
		extended.addActionListener(rad);
		paralel.addActionListener(rad);
		
		group.add(chartOnly);
		group.add(extended);
		group.add(paralel);
		extended.setSelected(true);
		
		result.add(chartOnly);
		result.add(extended);
		result.add(paralel);
		
		return result;
	}
	
	private JPanel TopSection(){
		JPanel result = new JPanel();
		result.setBorder(new BevelBorder(BevelBorder.LOWERED));		
		
		topWidths[0] = (int)(TOP_PERC[0]*WIDTH);
		topWidths[2] = (int)(TOP_PERC[2]*WIDTH);
		topWidths[1] = WIDTH - topWidths[0] - topWidths[2];
		
		panels[0] = TopSectionC1();
		panels[1] = TopSectionC2();
		panels[2] = TopSectionC3();
		
		result.add(panels[0]);
		result.add(panels[1]);
		result.add(panels[2]);		
		
		return result;
		
	}
	
	private JPanel MiddleSection(){
		Dimension midDim = new Dimension(WIDTH, (int)((1-BOT_HEIGHT_PERC-TOP_HEIGHT_PERC)*HEIGHT));
		JPanel result = graphView.getGraphView(midDim);
		
		result.setPreferredSize(midDim);
		result.setBorder(new BevelBorder(BevelBorder.LOWERED));
		
		
		return result;
		
	}
	
	protected void setHighSpeed(){		
		barGraph.setAnimationSpeed(HS_ANIMATION_TIMEOUT);
		graphView.setAnimationSpeed(HS_ANIMATION_TIMEOUT);
		this.turnEndTimeout = HS_ANIMATION_TIMEOUT * 10;
	}
	
	protected void setNormalSpeed(){
		barGraph.setAnimationSpeed(ANIMATION_TIMEOUT);
		graphView.setAnimationSpeed(HS_ANIMATION_TIMEOUT);
		this.turnEndTimeout = ANIMATION_TIMEOUT * 10;
	}
	
	protected void setStop(){
		simPlay = false;
	}	
	
	protected void setExtendedSim(boolean extSim){
		extendedSim = extSim;
	}
	
	protected void setParalelSim(boolean parSim){
		paralelSim = parSim;
	}

	
	protected void setActive(){
		this.simPlay = true;
	}
	
	protected void resumeUI(){
		paused = false;
	}
	
	protected void pauseUI(){
		paused = true;
		
	}
	
	private void pauseIt(){
		while(paused)
			try {
				Thread.currentThread().sleep(2);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}

	public EnvironmentView(Environment env) {
		this.env = env;
		simPlay = false;
		extendedSim = true;
		paralelSim = false;
		
		JFrame frame = new JFrame("Processors usage");
		
		frame.setSize(WIDTH, HEIGHT);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.barGraph = new BarGraph(env, ANIMATION_TIMEOUT);
		this.graphView = new GraphView(env, ANIMATION_TIMEOUT);
		
		JPanel botPan = BottomSection();
		JPanel topPan = TopSection();
		JPanel middlePan = MiddleSection();
		  
		frame.add(topPan, BorderLayout.NORTH);
		frame.add(botPan, BorderLayout.SOUTH);		
		frame.add(middlePan, BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);		
	}
	
	/**
	 * Main function to be called after then end of a step
	 */
	public void endOfTurn(){
		panels[1].removeAll();
		if (extendedSim || paralelSim){
			graphView.resetColour();
		}
		
		if (paralelSim){
			graphView.walkAgents();
			
		}
		barGraph.animate();
		graphView.resetColour();
		try {
			Thread.sleep(turnEndTimeout);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
	public void animateAgent(Agent x){
		if (extendedSim){
			pauseIt();
			JLabel jlabel = new JLabel("A"+x.getID());
			panels[1].removeAll();
		    jlabel.setFont(new Font("Verdana",1,90));
		    panels[1].add(jlabel);
		    panels[1].validate();
		    panels[1].repaint();
			graphView.animateAgent(x);
		}
	}
	
	
	
	public boolean isActive(){
		return simPlay;
	}
	
	 
	public void join() {
		// TODO: add shutdown logic here
	}
}
